package com.szy.assembly;

import java.io.Serializable;
import java.util.HashMap;

public class GPIO extends Peripheral implements Serializable {

    private final int offset_dir=0;
    private final int offset_odr=1;
    private final int offset_idr=2;
    private final int offset_ien=0x100;
    private final int offset_isrc=0x101;
    public GPIO(int baseAddress){
        super(baseAddress);
        registers=new HashMap<>();
        registers.put(base+offset_dir,0);
        registers.put(base+offset_odr,0);
        registers.put(base+offset_idr,0);
        registers.put(base+offset_ien,0);
        registers.put(base+offset_isrc,0);
    }

    @Override
    public boolean setRegister(int address, int value) {
        if(!super.setRegister(address, value)){
            return false;
        }

        //输出模式下，如果odr改变了，就需要改变对应引脚输出
        if(address == base + offset_odr){
            for(int i=0;i<8;i++){
                if(getBits(registers.get(base+offset_dir),i,1) == 1){
                    ioChangedNotifier.ioChanged(i,getBits(value,4*i,4));
                }
            }
        }else if(address == base + offset_dir){
            //如果模式改为输入，那么吧对应引脚的输出改为0，方式自身输出影响输入
            for(int i=0;i<8;i++){
                if(getBits(registers.get(base+offset_dir),i,1) == 0){
                    ioChangedNotifier.ioChanged(i,0);
                }
            }
        }



        return true;
    }



    @Override
    public void ioChangedByHardware(int ioNumber, int value) {
        super.ioChangedByHardware(ioNumber, value);
        if(getRegisterBits(base+offset_idr,ioNumber*4,4) != value){
            if(getRegisterBits(base+offset_ien,ioNumber*2,1) == 1){
                //上升沿触发
                if(getRegisterBits(base+offset_idr,ioNumber*4,4) == 0 && value !=0){
                    setRegisterBits(base+offset_isrc,ioNumber*2,1,1);
                    interruptRequest.interruptHandle(InterruptVector.InterruptName.EXTERNAL);
                }
            }
            if(getRegisterBits(base+offset_ien,ioNumber*2+1,1) == 1){
                //下降沿触发
                if(getRegisterBits(base+offset_idr,ioNumber*4,4) != 0 && value ==0){
                    setRegisterBits(base+offset_isrc,ioNumber*2+1,1,1);
                    interruptRequest.interruptHandle(InterruptVector.InterruptName.EXTERNAL);
                }
            }
            if(getRegisterBits(base+offset_dir,ioNumber,1) == 0){
                setRegisterBits(base+offset_idr,ioNumber*4,4,value);
            }

        }
    }
}
